package cz.semjob.document.annotation.metadata;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;

@Component
public class AnnotationTypeFactory implements Serializable {

	/**
	 * 
	 */
	private static final long serialVersionUID = 6987536155939017757L;
	private static Logger logger = Logger.getLogger(AnnotationTypeFactory.class);
	private Map<String, Entity> entities;
	private Map<String, Relation> relations;

	public static final String taxonomicRelationType = "taxonomic";
	public static final String nontaxonomicRelationType = "non-taxonomic";
	public static final String[] relationsTypes = new String[] {
			taxonomicRelationType, nontaxonomicRelationType };

	private final static Relation noneRelationTaxonomic = new Relation("NONE",
			taxonomicRelationType);
	private final static Relation noneRelationNonTaxonomic = new Relation(
			"NONE", nontaxonomicRelationType);
	private final static Relation[] noneRelations = new Relation[] {
			noneRelationTaxonomic, noneRelationNonTaxonomic };

	public AnnotationTypeFactory() {
		entities = new HashMap<String, Entity>();
		relations = new HashMap<String, Relation>();
	}

	public Entity getEntity(String entityName) {
		if (entities.containsKey(entityName)) {
			return entities.get(entityName);
		}
		//throw new AssertionError("Entity does not exist: " +entityName);
		logger.warn("Entity does not exist: " +entityName);
		return null;
	}

	public String[] getEntitiesNames() {
		return new ArrayList<String>(entities.keySet())
				.toArray(new String[entities.keySet().size()]);
	}

	public Relation getRelation(String relationName) {
		// handle the ThemeA, ThemeB occurences
		if (relations.containsKey(relationName)) {
			return relations.get(relationName);
		} else if (relations.containsKey(relationName.substring(0,
				relationName.length() - 1))) {
			return relations.get(relationName.substring(0,
					relationName.length() - 1));
			// } else {
			// Relation relation = new Relation(relationName);
			// relations.put(relationName, relation);
			// return relation;
		}
		//throw new AssertionError("Relation does not exist: " +relationName);
		logger.warn("Relation does not exist: " +relationName);
		return null;
	}

	public static Relation getNoneRelation(String type) {
		for (Relation relation : noneRelations) {
			if (type.equals(relation.getType())) {
				return relation;
			}
		}
		return null;
	}

	public List<Relation> getRelationsByType(String type) {
		if (Arrays.asList(relationsTypes).contains(type)) {
			List<Relation> filteredRelations = new ArrayList<Relation>();
			for (Relation relation : this.relations.values()) {
				if (relation.getType().equals(type)) {
					filteredRelations.add(relation);
				}

			}
			filteredRelations.add(getNoneRelation(type));
			return filteredRelations;
		} else {
			return null;
		}
	}

	public List<Entity> getAllEntities() {
		return new ArrayList<Entity>(entities.values());
	}

	public List<Relation> getAllRelations() {
		ArrayList<Relation> allRelations = new ArrayList<Relation>(
				relations.values());
		allRelations.addAll(Arrays.asList(noneRelations));
		return allRelations;
	}

	public void setEntities(Map<String, Entity> entities) {
		this.entities = entities;
	}

	public void setRelations(Map<String, Relation> relations) {
		this.relations = relations;
	}

	public static Relation[] getNoneRelations() {
		return noneRelations;
	}

	public AAnnotationType getAnnotationTypeByName(String name) {
		if (entities.get(name) != null) {
			return entities.get(name);
		}
		if (relations.get(name) != null) {
			return relations.get(name);
		}
		return null;
	}

}
